home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume15 / ggems / part05 < prev    next >
Encoding:
Text File  |  1990-10-14  |  52.7 KB  |  2,042 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: craig@weedeater.math.yale.edu
  3. subject: v15i027: Graphics Gems, Part 5/5
  4. from: Craig Kolb <craig@weedeater.math.yale.edu>
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 15, Issue 27
  8. Submitted-by: Craig Kolb <craig@weedeater.math.yale.edu>
  9. Archive-name: ggems/part05
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 5 (of 5)."
  18. # Contents:  AALines/FastMatMul.c FitCurves.c GGVecLib.c NearestPoint.c
  19. # Wrapped by craig@weedeater on Fri Oct 12 15:53:15 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'AALines/FastMatMul.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'AALines/FastMatMul.c'\"
  23. else
  24. echo shar: Extracting \"'AALines/FastMatMul.c'\" \(12335 characters\)
  25. sed "s/^X//" >'AALines/FastMatMul.c' <<'END_OF_FILE'
  26. X/*  FILENAME: FastMatMul.c  [revised 18 AUG 90]
  27. X
  28. X    AUTHOR:  Kelvin Thompson
  29. X
  30. X    DESCRIPTION:  Routines to multiply different kinds of 4x4
  31. X      matrices as fast as possible.  Based on ideas on pages 454,
  32. X      460-461, and 646 of _Graphics_Gems_.
  33. X
  34. X    These routines offer two advantages over the standard
  35. X      V3MatMul in the _Graphics_Gems_ vector library GGVecLib.c.
  36. X      First, the routines are faster.  Second, they can handle
  37. X      input matrices that are the same as the output matrix.
  38. X      The routines have the disadvantage of taking more code
  39. X      space (from unwound loops).
  40. X
  41. X        The routines are about as fast as you can get for
  42. X      general-purpose multiplication.  If you have special
  43. X      knowledge about your system, you may be able to improve
  44. X      them a little more:
  45. X
  46. X        [1]  If you know that your input and output matrices will
  47. X      never overlap: remove the tests near the beginning and end of
  48. X      each routine, and just #define 'mptr' to 'result'.  (The
  49. X      standard library's V3MatMul makes this assumption.)
  50. X
  51. X    [2]  If you know that your compiler supports more than
  52. X      three pointer-to-double registers in a subroutine: make
  53. X      'result' in each routine a register variable.  You might
  54. X      also make the 'usetemp' boolean a register.
  55. X
  56. X    [3]  If you have limited stack space, or your system can
  57. X      access global memory faster than stack:  make each routine's
  58. X      'tempx' a static, or let all routines share a global 'tempx'.
  59. X      (This is useless if assumption [1] holds.)
  60. X*/
  61. X
  62. X/* definitions from "GraphicsGems.h" */
  63. Xtypedef struct Matrix3Struct {    /* 3-by-3 matrix */
  64. X    double element[3][3];
  65. X    } Matrix3;
  66. Xtypedef struct Matrix4Struct {    /* 4-by-4 matrix */
  67. X    double element[4][4];
  68. X    } Matrix4;
  69. X
  70. X/* routines in this file */
  71. XMatrix3 *V2MatMul();     /* general 3x3 matrix multiplier */
  72. XMatrix4 *V3MatMul();     /* general 4x4 matrix multiplier */
  73. XMatrix4 *V3AffMatMul();  /* affine 4x4 matrix multiplier */
  74. XMatrix4 *V3LinMatMul();  /* linear 4x4 matrix multiplier */
  75. X
  76. X/* macro to access matrix element */
  77. X#define MVAL(mptr,row,col)  ((mptr)->element[row][col])
  78. X
  79. X
  80. X
  81. X
  82. X
  83. X/*  ************************************
  84. X    *                                  *
  85. X    *           V2MatMul               *
  86. X    *                                  *
  87. X    ************************************
  88. X
  89. X    DESCRIPTION:  Multiply two general 3x3 matricies.  If one of
  90. X      the input matrices is the same as the output, write the
  91. X      result to a temporary matrix during multiplication, then
  92. X      copy to the output matrix.
  93. X
  94. X    ENTRY:
  95. X      a -- pointer to left matrix
  96. X      b -- pointer to right matrix
  97. X      result -- result matrix
  98. X
  99. X    EXIT:  returns 'result'
  100. X*/
  101. X
  102. XMatrix3 *V2MatMul ( a, b, result )
  103. Xregister Matrix3 *a,*b;
  104. XMatrix3 *result;
  105. X{
  106. Xregister Matrix3 *mptr;
  107. Xint usetemp;  /* boolean */
  108. XMatrix3 tempx;
  109. X
  110. X/* decide where intermediate result goes */
  111. Xusetemp = ( a == result  ||  b == result );
  112. Xif ( usetemp )
  113. X  mptr = & tempx;
  114. Xelse
  115. X  mptr = result;
  116. X
  117. XMVAL(mptr,0,0) =
  118. X     MVAL(a,0,0) * MVAL(b,0,0)
  119. X  +  MVAL(a,0,1) * MVAL(b,1,0)
  120. X  +  MVAL(a,0,2) * MVAL(b,2,0);
  121. X
  122. XMVAL(mptr,0,1) =
  123. X     MVAL(a,0,0) * MVAL(b,0,1)
  124. X  +  MVAL(a,0,1) * MVAL(b,1,1)
  125. X  +  MVAL(a,0,2) * MVAL(b,2,1);
  126. X
  127. XMVAL(mptr,0,2) =
  128. X     MVAL(a,0,0) * MVAL(b,0,2)
  129. X  +  MVAL(a,0,1) * MVAL(b,1,2)
  130. X  +  MVAL(a,0,2) * MVAL(b,2,2);
  131. X
  132. XMVAL(mptr,1,0) =
  133. X     MVAL(a,1,0) * MVAL(b,0,0)
  134. X  +  MVAL(a,1,1) * MVAL(b,1,0)
  135. X  +  MVAL(a,1,2) * MVAL(b,2,0);
  136. X
  137. XMVAL(mptr,1,1) =
  138. X     MVAL(a,1,0) * MVAL(b,0,1)
  139. X  +  MVAL(a,1,1) * MVAL(b,1,1)
  140. X  +  MVAL(a,1,2) * MVAL(b,2,1);
  141. X
  142. XMVAL(mptr,1,2) =
  143. X     MVAL(a,1,0) * MVAL(b,0,2)
  144. X  +  MVAL(a,1,1) * MVAL(b,1,2)
  145. X  +  MVAL(a,1,2) * MVAL(b,2,2);
  146. X
  147. XMVAL(mptr,2,0) =
  148. X     MVAL(a,2,0) * MVAL(b,0,0)
  149. X  +  MVAL(a,2,1) * MVAL(b,1,0)
  150. X  +  MVAL(a,2,2) * MVAL(b,2,0);
  151. X
  152. XMVAL(mptr,2,1) =
  153. X     MVAL(a,2,0) * MVAL(b,0,1)
  154. X  +  MVAL(a,2,1) * MVAL(b,1,1)
  155. X  +  MVAL(a,2,2) * MVAL(b,2,1);
  156. X
  157. XMVAL(mptr,2,2) =
  158. X     MVAL(a,2,0) * MVAL(b,0,2)
  159. X  +  MVAL(a,2,1) * MVAL(b,1,2)
  160. X  +  MVAL(a,2,2) * MVAL(b,2,2);
  161. X
  162. X/* copy temp matrix to result if needed */
  163. Xif ( usetemp )
  164. X  *result = *mptr;
  165. X
  166. Xreturn result;
  167. X}
  168. X
  169. X
  170. X
  171. X
  172. X/*  ************************************
  173. X    *                                  *
  174. X    *           V3MatMul               *
  175. X    *                                  *
  176. X    ************************************
  177. X
  178. X    DESCRIPTION:  Multiply two general 4x4 matricies.  If one of
  179. X      the input matrices is the same as the output, write the
  180. X      result to a temporary matrix during multiplication, then
  181. X      copy to the output matrix.
  182. X
  183. X    ENTRY:
  184. X      a -- pointer to left matrix
  185. X      b -- pointer to right matrix
  186. X      result -- result matrix
  187. X
  188. X    EXIT:  returns 'result'
  189. X*/
  190. X
  191. XMatrix4 *V3MatMul ( a, b, result )
  192. Xregister Matrix4 *a,*b;
  193. XMatrix4 *result;
  194. X{
  195. Xregister Matrix4 *mptr;
  196. Xint usetemp;  /* boolean */
  197. XMatrix4 tempx;
  198. X
  199. X/* decide where intermediate result goes */
  200. Xusetemp = ( a == result  ||  b == result );
  201. Xif ( usetemp )
  202. X  mptr = & tempx;
  203. Xelse
  204. X  mptr = result;
  205. X
  206. XMVAL(mptr,0,0) =
  207. X     MVAL(a,0,0) * MVAL(b,0,0)
  208. X  +  MVAL(a,0,1) * MVAL(b,1,0)
  209. X  +  MVAL(a,0,2) * MVAL(b,2,0)
  210. X  +  MVAL(a,0,3) * MVAL(b,3,0);
  211. X
  212. XMVAL(mptr,0,1) =
  213. X     MVAL(a,0,0) * MVAL(b,0,1)
  214. X  +  MVAL(a,0,1) * MVAL(b,1,1)
  215. X  +  MVAL(a,0,2) * MVAL(b,2,1)
  216. X  +  MVAL(a,0,3) * MVAL(b,3,1);
  217. X
  218. XMVAL(mptr,0,2) =
  219. X     MVAL(a,0,0) * MVAL(b,0,2)
  220. X  +  MVAL(a,0,1) * MVAL(b,1,2)
  221. X  +  MVAL(a,0,2) * MVAL(b,2,2)
  222. X  +  MVAL(a,0,3) * MVAL(b,3,2);
  223. X
  224. XMVAL(mptr,0,3) =
  225. X     MVAL(a,0,0) * MVAL(b,0,3)
  226. X  +  MVAL(a,0,1) * MVAL(b,1,3)
  227. X  +  MVAL(a,0,2) * MVAL(b,2,3)
  228. X  +  MVAL(a,0,3) * MVAL(b,3,3);
  229. X
  230. XMVAL(mptr,1,0) =
  231. X     MVAL(a,1,0) * MVAL(b,0,0)
  232. X  +  MVAL(a,1,1) * MVAL(b,1,0)
  233. X  +  MVAL(a,1,2) * MVAL(b,2,0)
  234. X  +  MVAL(a,1,3) * MVAL(b,3,0);
  235. X
  236. XMVAL(mptr,1,1) =
  237. X     MVAL(a,1,0) * MVAL(b,0,1)
  238. X  +  MVAL(a,1,1) * MVAL(b,1,1)
  239. X  +  MVAL(a,1,2) * MVAL(b,2,1)
  240. X  +  MVAL(a,1,3) * MVAL(b,3,1);
  241. X
  242. XMVAL(mptr,1,2) =
  243. X     MVAL(a,1,0) * MVAL(b,0,2)
  244. X  +  MVAL(a,1,1) * MVAL(b,1,2)
  245. X  +  MVAL(a,1,2) * MVAL(b,2,2)
  246. X  +  MVAL(a,1,3) * MVAL(b,3,2);
  247. X
  248. XMVAL(mptr,1,3) =
  249. X     MVAL(a,1,0) * MVAL(b,0,3)
  250. X  +  MVAL(a,1,1) * MVAL(b,1,3)
  251. X  +  MVAL(a,1,2) * MVAL(b,2,3)
  252. X  +  MVAL(a,1,3) * MVAL(b,3,3);
  253. X
  254. XMVAL(mptr,2,0) =
  255. X     MVAL(a,2,0) * MVAL(b,0,0)
  256. X  +  MVAL(a,2,1) * MVAL(b,1,0)
  257. X  +  MVAL(a,2,2) * MVAL(b,2,0)
  258. X  +  MVAL(a,2,3) * MVAL(b,3,0);
  259. X
  260. XMVAL(mptr,2,1) =
  261. X     MVAL(a,2,0) * MVAL(b,0,1)
  262. X  +  MVAL(a,2,1) * MVAL(b,1,1)
  263. X  +  MVAL(a,2,2) * MVAL(b,2,1)
  264. X  +  MVAL(a,2,3) * MVAL(b,3,1);
  265. X
  266. XMVAL(mptr,2,2) =
  267. X     MVAL(a,2,0) * MVAL(b,0,2)
  268. X  +  MVAL(a,2,1) * MVAL(b,1,2)
  269. X  +  MVAL(a,2,2) * MVAL(b,2,2)
  270. X  +  MVAL(a,2,3) * MVAL(b,3,2);
  271. X
  272. XMVAL(mptr,2,3) =
  273. X     MVAL(a,2,0) * MVAL(b,0,3)
  274. X  +  MVAL(a,2,1) * MVAL(b,1,3)
  275. X  +  MVAL(a,2,2) * MVAL(b,2,3)
  276. X  +  MVAL(a,2,3) * MVAL(b,3,3);
  277. X
  278. XMVAL(mptr,3,0) =
  279. X     MVAL(a,3,0) * MVAL(b,0,0)
  280. X  +  MVAL(a,3,1) * MVAL(b,1,0)
  281. X  +  MVAL(a,3,2) * MVAL(b,2,0)
  282. X  +  MVAL(a,3,3) * MVAL(b,3,0);
  283. X
  284. XMVAL(mptr,3,1) =
  285. X     MVAL(a,3,0) * MVAL(b,0,1)
  286. X  +  MVAL(a,3,1) * MVAL(b,1,1)
  287. X  +  MVAL(a,3,2) * MVAL(b,2,1)
  288. X  +  MVAL(a,3,3) * MVAL(b,3,1);
  289. X
  290. XMVAL(mptr,3,2) =
  291. X     MVAL(a,3,0) * MVAL(b,0,2)
  292. X  +  MVAL(a,3,1) * MVAL(b,1,2)
  293. X  +  MVAL(a,3,2) * MVAL(b,2,2)
  294. X  +  MVAL(a,3,3) * MVAL(b,3,2);
  295. X
  296. XMVAL(mptr,3,3) =
  297. X     MVAL(a,3,0) * MVAL(b,0,3)
  298. X  +  MVAL(a,3,1) * MVAL(b,1,3)
  299. X  +  MVAL(a,3,2) * MVAL(b,2,3)
  300. X  +  MVAL(a,3,3) * MVAL(b,3,3);
  301. X
  302. X/* copy temp matrix to result if needed */
  303. Xif ( usetemp )
  304. X  *result = *mptr;
  305. X
  306. Xreturn result;
  307. X}
  308. X
  309. X
  310. X
  311. X
  312. X
  313. X/*  ************************************
  314. X    *                                  *
  315. X    *        V3AffMatMul               *
  316. X    *                                  *
  317. X    ************************************
  318. X
  319. X    DESCRIPTION:  Multiply two affine 4x4 matricies.  The
  320. X      routine assumes the rightmost column of each input
  321. X      matrix is [0 0 0 1].  The output matrix will have the
  322. X      same property.
  323. X    
  324. X      If one of the input matrices is the same as the output,
  325. X      write the result to a temporary matrix during multiplication,
  326. X      then copy to the output matrix.
  327. X
  328. X    ENTRY:
  329. X      a -- pointer to left matrix
  330. X      b -- pointer to right matrix
  331. X      result -- result matrix
  332. X
  333. X    EXIT:  returns 'result'
  334. X*/
  335. X
  336. XMatrix4 *V3AffMatMul ( a, b, result )
  337. Xregister Matrix4 *a,*b;
  338. XMatrix4 *result;
  339. X{
  340. Xregister Matrix4 *mptr;
  341. Xint usetemp;  /* boolean */
  342. XMatrix4 tempx;
  343. X
  344. X/* decide where intermediate result goes */
  345. Xusetemp = ( a == result  ||  b == result );
  346. Xif ( usetemp )
  347. X  mptr = & tempx;
  348. Xelse
  349. X  mptr = result;
  350. X
  351. XMVAL(mptr,0,0) =
  352. X     MVAL(a,0,0) * MVAL(b,0,0)
  353. X  +  MVAL(a,0,1) * MVAL(b,1,0)
  354. X  +  MVAL(a,0,2) * MVAL(b,2,0);
  355. X
  356. XMVAL(mptr,0,1) =
  357. X     MVAL(a,0,0) * MVAL(b,0,1)
  358. X  +  MVAL(a,0,1) * MVAL(b,1,1)
  359. X  +  MVAL(a,0,2) * MVAL(b,2,1);
  360. X
  361. XMVAL(mptr,0,2) =
  362. X     MVAL(a,0,0) * MVAL(b,0,2)
  363. X  +  MVAL(a,0,1) * MVAL(b,1,2)
  364. X  +  MVAL(a,0,2) * MVAL(b,2,2);
  365. X
  366. XMVAL(mptr,0,3) = 0.0;
  367. X
  368. XMVAL(mptr,1,0) =
  369. X     MVAL(a,1,0) * MVAL(b,0,0)
  370. X  +  MVAL(a,1,1) * MVAL(b,1,0)
  371. X  +  MVAL(a,1,2) * MVAL(b,2,0);
  372. X
  373. XMVAL(mptr,1,1) =
  374. X     MVAL(a,1,0) * MVAL(b,0,1)
  375. X  +  MVAL(a,1,1) * MVAL(b,1,1)
  376. X  +  MVAL(a,1,2) * MVAL(b,2,1);
  377. X
  378. XMVAL(mptr,1,2) =
  379. X     MVAL(a,1,0) * MVAL(b,0,2)
  380. X  +  MVAL(a,1,1) * MVAL(b,1,2)
  381. X  +  MVAL(a,1,2) * MVAL(b,2,2);
  382. X
  383. XMVAL(mptr,1,3) = 0.0;
  384. X
  385. XMVAL(mptr,2,0) =
  386. X     MVAL(a,2,0) * MVAL(b,0,0)
  387. X  +  MVAL(a,2,1) * MVAL(b,1,0)
  388. X  +  MVAL(a,2,2) * MVAL(b,2,0);
  389. X
  390. XMVAL(mptr,2,1) =
  391. X     MVAL(a,2,0) * MVAL(b,0,1)
  392. X  +  MVAL(a,2,1) * MVAL(b,1,1)
  393. X  +  MVAL(a,2,2) * MVAL(b,2,1);
  394. X
  395. XMVAL(mptr,2,2) =
  396. X     MVAL(a,2,0) * MVAL(b,0,2)
  397. X  +  MVAL(a,2,1) * MVAL(b,1,2)
  398. X  +  MVAL(a,2,2) * MVAL(b,2,2);
  399. X
  400. XMVAL(mptr,2,3) = 0.0;
  401. X
  402. XMVAL(mptr,3,0) =
  403. X     MVAL(a,3,0) * MVAL(b,0,0)
  404. X  +  MVAL(a,3,1) * MVAL(b,1,0)
  405. X  +  MVAL(a,3,2) * MVAL(b,2,0)
  406. X  +                MVAL(b,3,0);
  407. X
  408. XMVAL(mptr,3,1) =
  409. X     MVAL(a,3,0) * MVAL(b,0,1)
  410. X  +  MVAL(a,3,1) * MVAL(b,1,1)
  411. X  +  MVAL(a,3,2) * MVAL(b,2,1)
  412. X  +                MVAL(b,3,1);
  413. X
  414. XMVAL(mptr,3,2) =
  415. X     MVAL(a,3,0) * MVAL(b,0,2)
  416. X  +  MVAL(a,3,1) * MVAL(b,1,2)
  417. X  +  MVAL(a,3,2) * MVAL(b,2,2)
  418. X  +                MVAL(b,3,2);
  419. X
  420. XMVAL(mptr,3,3) = 1.0;
  421. X
  422. X/* copy temp matrix to result if needed */
  423. Xif ( usetemp )
  424. X  *result = *mptr;
  425. X
  426. Xreturn result;
  427. X}
  428. X
  429. X
  430. X
  431. X
  432. X
  433. X/*  ************************************
  434. X    *                                  *
  435. X    *        V3LinMatMul               *
  436. X    *                                  *
  437. X    ************************************
  438. X
  439. X    DESCRIPTION:  Multiply two affine 4x4 matricies.  The
  440. X      routine assumes the right column and bottom line
  441. X      of each input matrix is [0 0 0 1].  The output matrix
  442. X      will have the same property.  This is pretty much the
  443. X      same thing as multiplying two 3x3 matrices.
  444. X    
  445. X      If one of the input matrices is the same as the output,
  446. X      write the result to a temporary matrix during multiplication,
  447. X      then copy to the output matrix.
  448. X
  449. X    ENTRY:
  450. X      a -- pointer to left matrix
  451. X      b -- pointer to right matrix
  452. X      result -- result matrix
  453. X
  454. X    EXIT:  returns 'result'
  455. X*/
  456. X
  457. XMatrix4 *V3LinMatMul ( a, b, result )
  458. Xregister Matrix4 *a,*b;
  459. XMatrix4 *result;
  460. X{
  461. Xregister Matrix4 *mptr;
  462. Xint usetemp;  /* boolean */
  463. XMatrix4 tempx;
  464. X
  465. X/* decide where intermediate result goes */
  466. Xusetemp = ( a == result  ||  b == result );
  467. Xif ( usetemp )
  468. X  mptr = & tempx;
  469. Xelse
  470. X  mptr = result;
  471. X
  472. XMVAL(mptr,0,0) =
  473. X     MVAL(a,0,0) * MVAL(b,0,0)
  474. X  +  MVAL(a,0,1) * MVAL(b,1,0)
  475. X  +  MVAL(a,0,2) * MVAL(b,2,0);
  476. X
  477. XMVAL(mptr,0,1) =
  478. X     MVAL(a,0,0) * MVAL(b,0,1)
  479. X  +  MVAL(a,0,1) * MVAL(b,1,1)
  480. X  +  MVAL(a,0,2) * MVAL(b,2,1);
  481. X
  482. XMVAL(mptr,0,2) =
  483. X     MVAL(a,0,0) * MVAL(b,0,2)
  484. X  +  MVAL(a,0,1) * MVAL(b,1,2)
  485. X  +  MVAL(a,0,2) * MVAL(b,2,2);
  486. X
  487. XMVAL(mptr,0,3) = 0.0;
  488. X
  489. XMVAL(mptr,1,0) =
  490. X     MVAL(a,1,0) * MVAL(b,0,0)
  491. X  +  MVAL(a,1,1) * MVAL(b,1,0)
  492. X  +  MVAL(a,1,2) * MVAL(b,2,0);
  493. X
  494. XMVAL(mptr,1,1) =
  495. X     MVAL(a,1,0) * MVAL(b,0,1)
  496. X  +  MVAL(a,1,1) * MVAL(b,1,1)
  497. X  +  MVAL(a,1,2) * MVAL(b,2,1);
  498. X
  499. XMVAL(mptr,1,2) =
  500. X     MVAL(a,1,0) * MVAL(b,0,2)
  501. X  +  MVAL(a,1,1) * MVAL(b,1,2)
  502. X  +  MVAL(a,1,2) * MVAL(b,2,2);
  503. X
  504. XMVAL(mptr,1,3) = 0.0;
  505. X
  506. XMVAL(mptr,2,0) =
  507. X     MVAL(a,2,0) * MVAL(b,0,0)
  508. X  +  MVAL(a,2,1) * MVAL(b,1,0)
  509. X  +  MVAL(a,2,2) * MVAL(b,2,0);
  510. X
  511. XMVAL(mptr,2,1) =
  512. X     MVAL(a,2,0) * MVAL(b,0,1)
  513. X  +  MVAL(a,2,1) * MVAL(b,1,1)
  514. X  +  MVAL(a,2,2) * MVAL(b,2,1);
  515. X
  516. XMVAL(mptr,2,2) =
  517. X     MVAL(a,2,0) * MVAL(b,0,2)
  518. X  +  MVAL(a,2,1) * MVAL(b,1,2)
  519. X  +  MVAL(a,2,2) * MVAL(b,2,2);
  520. X
  521. XMVAL(mptr,2,3) = 0.0;
  522. X
  523. XMVAL(mptr,3,0) = 0.0;
  524. XMVAL(mptr,3,1) = 0.0;
  525. XMVAL(mptr,3,2) = 0.0;
  526. XMVAL(mptr,3,3) = 1.0;
  527. X
  528. X/* copy temp matrix to result if needed */
  529. Xif ( usetemp )
  530. X  *result = *mptr;
  531. X
  532. Xreturn result;
  533. X}
  534. END_OF_FILE
  535. if test 12335 -ne `wc -c <'AALines/FastMatMul.c'`; then
  536.     echo shar: \"'AALines/FastMatMul.c'\" unpacked with wrong size!
  537. fi
  538. # end of 'AALines/FastMatMul.c'
  539. fi
  540. if test -f 'FitCurves.c' -a "${1}" != "-c" ; then 
  541.   echo shar: Will not clobber existing file \"'FitCurves.c'\"
  542. else
  543. echo shar: Extracting \"'FitCurves.c'\" \(14420 characters\)
  544. sed "s/^X//" >'FitCurves.c' <<'END_OF_FILE'
  545. X/*
  546. XAn Algorithm for Automatically Fitting Digitized Curves
  547. Xby Philip J. Schneider
  548. Xfrom "Graphics Gems", Academic Press, 1990
  549. X*/
  550. X
  551. X#define TESTMODE
  552. X
  553. X/*  fit_cubic.c    */                                    
  554. X/*    Piecewise cubic fitting code    */
  555. X
  556. X#include "GraphicsGems.h"                    
  557. X#include <stdio.h>
  558. X#include <malloc.h>
  559. X#include <math.h>
  560. X
  561. Xtypedef Point2 *BezierCurve;
  562. X
  563. X/* Forward declarations */
  564. Xvoid        FitCurve();
  565. Xstatic    void        FitCubic();
  566. Xstatic    double        *Reparameterize();
  567. Xstatic    double        NewtonRaphsonRootFind();
  568. Xstatic    Point2        Bezier();
  569. Xstatic    double         B0(), B1(), B2(), B3();
  570. Xstatic    Vector2        ComputeLeftTangent();
  571. Xstatic    Vector2        ComputeRightTangent();
  572. Xstatic    Vector2        ComputeCenterTangent();
  573. Xstatic    double        ComputeMaxError();
  574. Xstatic    double        *ChordLengthParameterize();
  575. Xstatic    BezierCurve    GenerateBezier();
  576. Xstatic    Vector2        V2AddII();
  577. Xstatic    Vector2        V2ScaleII();
  578. Xstatic    Vector2        V2SubII();
  579. X
  580. X#define MAXPOINTS    1000        /* The most points you can have */
  581. X
  582. X#ifdef TESTMODE
  583. X
  584. XDrawBezierCurve(n, curve)
  585. Xint n;
  586. XBezierCurve curve;
  587. X{
  588. X    /* You'll have to write this yourself. */
  589. X}
  590. X
  591. X/*
  592. X *  main:
  593. X *    Example of how to use the curve-fitting code.  Given an array
  594. X *   of points and a tolerance (squared error between points and 
  595. X *    fitted curve), the algorithm will generate a piecewise
  596. X *    cubic Bezier representation that approximates the points.
  597. X *    When a cubic is generated, the routine "DrawBezierCurve"
  598. X *    is called, which outputs the Bezier curve just created
  599. X *    (arguments are the degree and the control points, respectively).
  600. X *    Users will have to implement this function themselves     
  601. X *   ascii output, etc. 
  602. X *
  603. X */
  604. Xmain()
  605. X{
  606. X    static Point2 d[7] = {    /*  Digitized points */
  607. X    { 0.0, 0.0 },
  608. X    { 0.0, 0.5 },
  609. X    { 1.1, 1.4 },
  610. X    { 2.1, 1.6 },
  611. X    { 3.2, 1.1 },
  612. X    { 4.0, 0.2 },
  613. X    { 4.0, 0.0 },
  614. X    };
  615. X    double    error = 4.0;        /*  Squared error */
  616. X    FitCurve(d, 7, error);        /*  Fit the Bezier curves */
  617. X}
  618. X#endif                         /* TESTMODE */
  619. X
  620. X/*
  621. X *  FitCurve :
  622. X *      Fit a Bezier curve to a set of digitized points 
  623. X */
  624. Xvoid FitCurve(d, nPts, error)
  625. X    Point2    *d;            /*  Array of digitized points    */
  626. X    int        nPts;        /*  Number of digitized points    */
  627. X    double    error;        /*  User-defined error squared    */
  628. X{
  629. X    Vector2    tHat1, tHat2;    /*  Unit tangent vectors at endpoints */
  630. X
  631. X    tHat1 = ComputeLeftTangent(d, 0);
  632. X    tHat2 = ComputeRightTangent(d, nPts - 1);
  633. X    FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
  634. X}
  635. X
  636. X
  637. X
  638. X/*
  639. X *  FitCubic :
  640. X *      Fit a Bezier curve to a (sub)set of digitized points
  641. X */
  642. Xstatic void FitCubic(d, first, last, tHat1, tHat2, error)
  643. X    Point2    *d;            /*  Array of digitized points */
  644. X    int        first, last;    /* Indices of first and last pts in region */
  645. X    Vector2    tHat1, tHat2;    /* Unit tangent vectors at endpoints */
  646. X    double    error;        /*  User-defined error squared       */
  647. X{
  648. X    BezierCurve    bezCurve; /*Control points of fitted Bezier curve*/
  649. X    double    *u;        /*  Parameter values for point  */
  650. X    double    *uPrime;    /*  Improved parameter values */
  651. X    double    maxError;    /*  Maximum fitting error     */
  652. X    int        splitPoint;    /*  Point to split point set at     */
  653. X    int        nPts;        /*  Number of points in subset  */
  654. X    double    iterationError; /*Error below which you try iterating  */
  655. X    int        maxIterations = 4; /*  Max times to try iterating  */
  656. X    Vector2    tHatCenter;       /* Unit tangent vector at splitPoint */
  657. X    int        i;        
  658. X
  659. X    iterationError = error * error;
  660. X    nPts = last - first + 1;
  661. X
  662. X    /*  Use heuristic if region only has two points in it */
  663. X    if (nPts == 2) {
  664. X        double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
  665. X
  666. X        bezCurve = (Point2 *)malloc(4 * sizeof(Point2));
  667. X        bezCurve[0] = d[first];
  668. X        bezCurve[3] = d[last];
  669. X        V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
  670. X        V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
  671. X        DrawBezierCurve(3, bezCurve);
  672. X        return;
  673. X    }
  674. X
  675. X    /*  Parameterize points, and attempt to fit curve */
  676. X    u = ChordLengthParameterize(d, first, last);
  677. X    bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
  678. X
  679. X    /*  Find max deviation of points to fitted curve */
  680. X    maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
  681. X    if (maxError < error) {
  682. X        DrawBezierCurve(3, bezCurve);
  683. X        return;
  684. X    }
  685. X
  686. X
  687. X    /*  If error not too large, try some reparameterization  */
  688. X    /*  and iteration */
  689. X    if (maxError < iterationError) {
  690. X        for (i = 0; i < maxIterations; i++) {
  691. X            uPrime = Reparameterize(d, first, last, u, bezCurve);
  692. X            bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
  693. X            maxError = ComputeMaxError(d, first, last,
  694. X                       bezCurve, uPrime, &splitPoint);
  695. X            if (maxError < error) {
  696. X            DrawBezierCurve(3, bezCurve);
  697. X            return;
  698. X        }
  699. X        free((char *)u);
  700. X        u = uPrime;
  701. X    }
  702. X}
  703. X
  704. X    /* Fitting failed -- split at max error point and fit recursively */
  705. X    tHatCenter = ComputeCenterTangent(d, splitPoint);
  706. X    FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
  707. X    V2Negate(&tHatCenter);
  708. X    FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
  709. X}
  710. X
  711. X
  712. X/*
  713. X *  GenerateBezier :
  714. X *  Use least-squares method to find Bezier control points for region.
  715. X *
  716. X */
  717. Xstatic BezierCurve  GenerateBezier(d, first, last, uPrime, tHat1, tHat2)
  718. X    Point2    *d;            /*  Array of digitized points    */
  719. X    int        first, last;        /*  Indices defining region    */
  720. X    double    *uPrime;        /*  Parameter values for region */
  721. X    Vector2    tHat1, tHat2;    /*  Unit tangents at endpoints    */
  722. X{
  723. X    int     i;
  724. X    Vector2     A[MAXPOINTS][2];    /* Precomputed rhs for eqn    */
  725. X    int     nPts;            /* Number of pts in sub-curve */
  726. X    double     C[2][2];            /* Matrix C        */
  727. X    double     X[2];            /* Matrix X            */
  728. X    double     det_C0_C1,        /* Determinants of matrices    */
  729. X               det_C0_X,
  730. X               det_X_C1;
  731. X    double     alpha_l,        /* Alpha values, left and right    */
  732. X               alpha_r;
  733. X    Vector2     tmp;            /* Utility variable        */
  734. X    BezierCurve    bezCurve;    /* RETURN bezier curve ctl pts    */
  735. X
  736. X    bezCurve = (Point2 *)malloc(4 * sizeof(Point2));
  737. X    nPts = last - first + 1;
  738. X
  739. X    /* Compute the A's    */
  740. X    for (i = 0; i < nPts; i++) {
  741. X        Vector2        v1, v2;
  742. X        v1 = tHat1;
  743. X        v2 = tHat2;
  744. X        V2Scale(&v1, B1(uPrime[i]));
  745. X        V2Scale(&v2, B2(uPrime[i]));
  746. X        A[i][0] = v1;
  747. X        A[i][1] = v2;
  748. X    }
  749. X
  750. X    /* Create the C and X matrices    */
  751. X    C[0][0] = 0.0;
  752. X    C[0][1] = 0.0;
  753. X    C[1][0] = 0.0;
  754. X    C[1][1] = 0.0;
  755. X    X[0]    = 0.0;
  756. X    X[1]    = 0.0;
  757. X
  758. X    for (i = 0; i < nPts; i++) {
  759. X        C[0][0] += V2Dot(&A[i][0], &A[i][0]);
  760. X        C[0][1] += V2Dot(&A[i][0], &A[i][1]);
  761. X/*                    C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/    
  762. X        C[1][0] = C[0][1];
  763. X        C[1][1] += V2Dot(&A[i][1], &A[i][1]);
  764. X
  765. X        tmp = V2SubII(d[first + i],
  766. X            V2AddII(
  767. X              V2ScaleII(d[first], B0(uPrime[i])),
  768. X                V2AddII(
  769. X                      V2ScaleII(d[first], B1(uPrime[i])),
  770. X                            V2AddII(
  771. X                              V2ScaleII(d[last], B2(uPrime[i])),
  772. X                                V2ScaleII(d[last], B3(uPrime[i]))))));
  773. X    
  774. X
  775. X    X[0] += V2Dot(&A[i][0], &tmp);
  776. X    X[1] += V2Dot(&A[i][1], &tmp);
  777. X    }
  778. X
  779. X    /* Compute the determinants of C and X    */
  780. X    det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
  781. X    det_C0_X  = C[0][0] * X[1]    - C[0][1] * X[0];
  782. X    det_X_C1  = X[0]    * C[1][1] - X[1]    * C[0][1];
  783. X
  784. X    /* Finally, derive alpha values    */
  785. X    if (det_C0_C1 == 0.0) {
  786. X        det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
  787. X    }
  788. X    alpha_l = det_X_C1 / det_C0_C1;
  789. X    alpha_r = det_C0_X / det_C0_C1;
  790. X
  791. X
  792. X    /*  If alpha negative, use the Wu/Barsky heuristic (see text) */
  793. X    if (alpha_l < 0.0 || alpha_r < 0.0) {
  794. X        double    dist = V2DistanceBetween2Points(&d[last], &d[first]) /
  795. X                    3.0;
  796. X
  797. X        bezCurve[0] = d[first];
  798. X        bezCurve[3] = d[last];
  799. X        V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
  800. X        V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
  801. X        return (bezCurve);
  802. X    }
  803. X
  804. X    /*  First and last control points of the Bezier curve are */
  805. X    /*  positioned exactly at the first and last data points */
  806. X    /*  Control points 1 and 2 are positioned an alpha distance out */
  807. X    /*  on the tangent vectors, left and right, respectively */
  808. X    bezCurve[0] = d[first];
  809. X    bezCurve[3] = d[last];
  810. X    V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
  811. X    V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
  812. X    return (bezCurve);
  813. X}
  814. X
  815. X
  816. X/*
  817. X *  Reparameterize:
  818. X *    Given set of points and their parameterization, try to find
  819. X *   a better parameterization.
  820. X *
  821. X */
  822. Xstatic double *Reparameterize(d, first, last, u, bezCurve)
  823. X    Point2    *d;            /*  Array of digitized points    */
  824. X    int        first, last;        /*  Indices defining region    */
  825. X    double    *u;            /*  Current parameter values    */
  826. X    BezierCurve    bezCurve;    /*  Current fitted curve    */
  827. X{
  828. X    int     nPts = last-first+1;    
  829. X    int     i;
  830. X    double    *uPrime;        /*  New parameter values    */
  831. X
  832. X    uPrime = (double *)malloc(nPts * sizeof(double));
  833. X    for (i = first; i <= last; i++) {
  834. X        uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-
  835. X                    first]);
  836. X    }
  837. X    return (uPrime);
  838. X}
  839. X
  840. X
  841. X
  842. X/*
  843. X *  NewtonRaphsonRootFind :
  844. X *    Use Newton-Raphson iteration to find better root.
  845. X */
  846. Xstatic double NewtonRaphsonRootFind(Q, P, u)
  847. X    BezierCurve    Q;            /*  Current fitted curve    */
  848. X    Point2         P;        /*  Digitized point        */
  849. X    double         u;        /*  Parameter value for "P"    */
  850. X{
  851. X    double         numerator, denominator;
  852. X    Point2         Q1[3], Q2[2];    /*  Q' and Q''            */
  853. X    Point2        Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q''    */
  854. X    double         uPrime;        /*  Improved u            */
  855. X    int         i;
  856. X    
  857. X    /* Compute Q(u)    */
  858. X    Q_u = Bezier(3, Q, u);
  859. X    
  860. X    /* Generate control vertices for Q'    */
  861. X    for (i = 0; i <= 2; i++) {
  862. X        Q1[i].x = (Q[i+1].x - Q[i].x) * 3.0;
  863. X        Q1[i].y = (Q[i+1].y - Q[i].y) * 3.0;
  864. X    }
  865. X    
  866. X    /* Generate control vertices for Q'' */
  867. X    for (i = 0; i <= 1; i++) {
  868. X        Q2[i].x = (Q1[i+1].x - Q1[i].x) * 2.0;
  869. X        Q2[i].y = (Q1[i+1].y - Q1[i].y) * 2.0;
  870. X    }
  871. X    
  872. X    /* Compute Q'(u) and Q''(u)    */
  873. X    Q1_u = Bezier(2, Q1, u);
  874. X    Q2_u = Bezier(1, Q2, u);
  875. X    
  876. X    /* Compute f(u)/f'(u) */
  877. X    numerator = (Q_u.x - P.x) * (Q1_u.x) + (Q_u.y - P.y) * (Q1_u.y);
  878. X    denominator = (Q1_u.x) * (Q1_u.x) + (Q1_u.y) * (Q1_u.y) +
  879. X                    (Q_u.x - P.x) * (Q2_u.x) + (Q_u.y - P.y) * (Q2_u.y);
  880. X    
  881. X    /* u = u - f(u)/f'(u) */
  882. X    uPrime = u - (numerator/denominator);
  883. X    return (uPrime);
  884. X}
  885. X
  886. X    
  887. X               
  888. X/*
  889. X *  Bezier :
  890. X *      Evaluate a Bezier curve at a particular parameter value
  891. X * 
  892. X */
  893. Xstatic Point2 Bezier(degree, V, t)
  894. X    int        degree;        /* The degree of the bezier curve    */
  895. X    Point2     *V;        /* Array of control points        */
  896. X    double     t;        /* Parametric value to find point for    */
  897. X{
  898. X    int     i, j;        
  899. X    Point2     Q;            /* Point on curve at parameter t    */
  900. X    Point2     *Vtemp;        /* Local copy of control points        */
  901. X
  902. X    /* Copy array    */
  903. X    Vtemp = (Point2 *)malloc((unsigned)((degree+1) 
  904. X                * sizeof (Point2)));
  905. X    for (i = 0; i <= degree; i++) {
  906. X        Vtemp[i] = V[i];
  907. X    }
  908. X
  909. X    /* Triangle computation    */
  910. X    for (i = 1; i <= degree; i++) {    
  911. X        for (j = 0; j <= degree-i; j++) {
  912. X            Vtemp[j].x = (1.0 - t) * Vtemp[j].x + t * Vtemp[j+1].x;
  913. X            Vtemp[j].y = (1.0 - t) * Vtemp[j].y + t * Vtemp[j+1].y;
  914. X        }
  915. X    }
  916. X
  917. X    Q = Vtemp[0];
  918. X    free((char *)Vtemp);
  919. X    return Q;
  920. X}
  921. X
  922. X
  923. X/*
  924. X *  B0, B1, B2, B3 :
  925. X *    Bezier multipliers
  926. X */
  927. Xstatic double B0(u)
  928. X    double    u;
  929. X{
  930. X    double tmp = 1.0 - u;
  931. X    return (tmp * tmp * tmp);
  932. X}
  933. X
  934. X
  935. Xstatic double B1(u)
  936. X    double    u;
  937. X{
  938. X    double tmp = 1.0 - u;
  939. X    return (3 * u * (tmp * tmp));
  940. X}
  941. X
  942. Xstatic double B2(u)
  943. X    double    u;
  944. X{
  945. X    double tmp = 1.0 - u;
  946. X    return (3 * u * u * tmp);
  947. X}
  948. X
  949. Xstatic double B3(u)
  950. X    double    u;
  951. X{
  952. X    return (u * u * u);
  953. X}
  954. X
  955. X
  956. X
  957. X/*
  958. X * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
  959. X *Approximate unit tangents at endpoints and "center" of digitized curve
  960. X */
  961. Xstatic Vector2 ComputeLeftTangent(d, end)
  962. X    Point2    *d;            /*  Digitized points*/
  963. X    int        end;        /*  Index to "left" end of region */
  964. X{
  965. X    Vector2    tHat1;
  966. X    tHat1 = V2SubII(d[end+1], d[end]);
  967. X    tHat1 = *V2Normalize(&tHat1);
  968. X    return tHat1;
  969. X}
  970. X
  971. Xstatic Vector2 ComputeRightTangent(d, end)
  972. X    Point2    *d;            /*  Digitized points        */
  973. X    int        end;        /*  Index to "right" end of region */
  974. X{
  975. X    Vector2    tHat2;
  976. X    tHat2 = V2SubII(d[end-1], d[end]);
  977. X    tHat2 = *V2Normalize(&tHat2);
  978. X    return tHat2;
  979. X}
  980. X
  981. X
  982. Xstatic Vector2 ComputeCenterTangent(d, center)
  983. X    Point2    *d;            /*  Digitized points            */
  984. X    int        center;        /*  Index to point inside region    */
  985. X{
  986. X    Vector2    V1, V2, tHatCenter;
  987. X
  988. X    V1 = V2SubII(d[center-1], d[center]);
  989. X    V2 = V2SubII(d[center], d[center+1]);
  990. X    tHatCenter.x = (V1.x + V2.x)/2.0;
  991. X    tHatCenter.y = (V1.y + V2.y)/2.0;
  992. X    tHatCenter = *V2Normalize(&tHatCenter);
  993. X    return tHatCenter;
  994. X}
  995. X
  996. X
  997. X/*
  998. X *  ChordLengthParameterize :
  999. X *    Assign parameter values to digitized points 
  1000. X *    using relative distances between points.
  1001. X */
  1002. Xstatic double *ChordLengthParameterize(d, first, last)
  1003. X    Point2    *d;            /* Array of digitized points */
  1004. X    int        first, last;        /*  Indices defining region    */
  1005. X{
  1006. X    int        i;    
  1007. X    double    *u;            /*  Parameterization        */
  1008. X
  1009. X    u = (double *)malloc((unsigned)(last-first+1) * sizeof(double));
  1010. X
  1011. X    u[0] = 0.0;
  1012. X    for (i = first+1; i <= last; i++) {
  1013. X        u[i-first] = u[i-first-1] +
  1014. X                  V2DistanceBetween2Points(&d[i], &d[i-1]);
  1015. X    }
  1016. X
  1017. X    for (i = first + 1; i <= last; i++) {
  1018. X        u[i-first] = u[i-first] / u[last-first];
  1019. X    }
  1020. X
  1021. X    return(u);
  1022. X}
  1023. X
  1024. X
  1025. X
  1026. X
  1027. X/*
  1028. X *  ComputeMaxError :
  1029. X *    Find the maximum squared distance of digitized points
  1030. X *    to fitted curve.
  1031. X*/
  1032. Xstatic double ComputeMaxError(d, first, last, bezCurve, u, splitPoint)
  1033. X    Point2    *d;            /*  Array of digitized points    */
  1034. X    int        first, last;        /*  Indices defining region    */
  1035. X    BezierCurve    bezCurve;        /*  Fitted Bezier curve        */
  1036. X    double    *u;            /*  Parameterization of points    */
  1037. X    int        *splitPoint;        /*  Point of maximum error    */
  1038. X{
  1039. X    int        i;
  1040. X    double    maxDist;        /*  Maximum error        */
  1041. X    double    dist;        /*  Current error        */
  1042. X    Point2    P;            /*  Point on curve        */
  1043. X    Vector2    v;            /*  Vector from point to curve    */
  1044. X
  1045. X    *splitPoint = (last - first + 1)/2;
  1046. X    maxDist = 0.0;
  1047. X    for (i = first + 1; i < last; i++) {
  1048. X        P = Bezier(3, bezCurve, u[i-first]);
  1049. X        v = V2SubII(P, d[i]);
  1050. X        dist = V2SquaredLength(&v);
  1051. X        if (dist >= maxDist) {
  1052. X            maxDist = dist;
  1053. X            *splitPoint = i;
  1054. X        }
  1055. X    }
  1056. X    return (maxDist);
  1057. X}
  1058. Xstatic Vector2 V2AddII(a, b)
  1059. X    Vector2 a, b;
  1060. X{
  1061. X    Vector2    c;
  1062. X    c.x = a.x + b.x;  c.y = a.y + b.y;
  1063. X    return (c);
  1064. X}
  1065. Xstatic Vector2 V2ScaleII(v, s)
  1066. X    Vector2    v;
  1067. X    double    s;
  1068. X{
  1069. X    Vector2 result;
  1070. X    result.x = v.x * s; result.y = v.y * s;
  1071. X    return (result);
  1072. X}
  1073. X
  1074. Xstatic Vector2 V2SubII(a, b)
  1075. X    Vector2    a, b;
  1076. X{
  1077. X    Vector2    c;
  1078. X    c.x = a.x - b.x; c.y = a.y - b.y;
  1079. X    return (c);
  1080. X}
  1081. END_OF_FILE
  1082. if test 14420 -ne `wc -c <'FitCurves.c'`; then
  1083.     echo shar: \"'FitCurves.c'\" unpacked with wrong size!
  1084. fi
  1085. # end of 'FitCurves.c'
  1086. fi
  1087. if test -f 'GGVecLib.c' -a "${1}" != "-c" ; then 
  1088.   echo shar: Will not clobber existing file \"'GGVecLib.c'\"
  1089. else
  1090. echo shar: Extracting \"'GGVecLib.c'\" \(10092 characters\)
  1091. sed "s/^X//" >'GGVecLib.c' <<'END_OF_FILE'
  1092. X/* 
  1093. X2d and 3d Vector C Library 
  1094. Xby Andrew Glassner
  1095. Xfrom "Graphics Gems", Academic Press, 1990
  1096. X*/
  1097. X
  1098. X#include <math.h>
  1099. X#include "GraphicsGems.h"
  1100. X
  1101. X/******************/
  1102. X/*   2d Library   */
  1103. X/******************/
  1104. X
  1105. X/* returns squared length of input vector */    
  1106. Xdouble V2SquaredLength(a) 
  1107. XVector2 *a;
  1108. X{    return((a->x * a->x)+(a->y * a->y));
  1109. X    };
  1110. X    
  1111. X/* returns length of input vector */
  1112. Xdouble V2Length(a) 
  1113. XVector2 *a;
  1114. X{
  1115. X    return(sqrt(V2SquaredLength(a)));
  1116. X    };
  1117. X    
  1118. X/* negates the input vector and returns it */
  1119. XVector2 *V2Negate(v) 
  1120. XVector2 *v;
  1121. X{
  1122. X    v->x = -v->x;  v->y = -v->y;
  1123. X    return(v);
  1124. X    };
  1125. X
  1126. X/* normalizes the input vector and returns it */
  1127. XVector2 *V2Normalize(v) 
  1128. XVector2 *v;
  1129. X{
  1130. Xdouble len = V2Length(v);
  1131. X    if (len != 0.0) { v->x /= len;  v->y /= len; };
  1132. X    return(v);
  1133. X    };
  1134. X
  1135. X
  1136. X/* scales the input vector to the new length and returns it */
  1137. XVector2 *V2Scale(v, newlen) 
  1138. XVector2 *v;
  1139. Xdouble newlen;
  1140. X{
  1141. Xdouble len = V2Length(v);
  1142. X    if (len != 0.0) { v->x *= newlen/len;   v->y *= newlen/len; };
  1143. X    return(v);
  1144. X    };
  1145. X
  1146. X/* return vector sum c = a+b */
  1147. XVector2 *V2Add(a, b, c)
  1148. XVector2 *a, *b, *c;
  1149. X{
  1150. X    c->x = a->x+b->x;  c->y = a->y+b->y;
  1151. X    return(c);
  1152. X    };
  1153. X    
  1154. X/* return vector difference c = a-b */
  1155. XVector2 *V2Sub(a, b, c)
  1156. XVector2 *a, *b, *c;
  1157. X{
  1158. X    c->x = a->x-b->x;  c->y = a->y-b->y;
  1159. X    return(c);
  1160. X    };
  1161. X
  1162. X/* return the dot product of vectors a and b */
  1163. Xdouble V2Dot(a, b) 
  1164. XVector2 *a, *b; 
  1165. X{
  1166. X    return((a->x*b->x)+(a->y*b->y));
  1167. X    };
  1168. X
  1169. X/* linearly interpolate between vectors by an amount alpha */
  1170. X/* and return the resulting vector. */
  1171. X/* When alpha=0, result=lo.  When alpha=1, result=hi. */
  1172. XVector2 *V2Lerp(lo, hi, alpha, result) 
  1173. XVector2 *lo, *hi, *result; 
  1174. Xdouble alpha;
  1175. X{
  1176. X    result->x = LERP(alpha, lo->x, hi->x);
  1177. X    result->y = LERP(alpha, lo->y, hi->y);
  1178. X    return(result);
  1179. X    };
  1180. X
  1181. X
  1182. X/* make a linear combination of two vectors and return the result. */
  1183. X/* result = (a * ascl) + (b * bscl) */
  1184. XVector2 *V2Combine (a, b, result, ascl, bscl) 
  1185. XVector2 *a, *b, *result;
  1186. Xdouble ascl, bscl;
  1187. X{
  1188. X    result->x = (ascl * a->x) + (bscl * b->x);
  1189. X    result->y = (ascl * a->y) + (bscl * b->y);
  1190. X    return(result);
  1191. X    };
  1192. X
  1193. X/* multiply two vectors together component-wise */
  1194. XVector2 *V2Mul (a, b, result) 
  1195. XVector2 *a, *b, *result;
  1196. X{
  1197. X    result->x = a->x * b->x;
  1198. X    result->y = a->y * b->y;
  1199. X    return(result);
  1200. X    };
  1201. X
  1202. X/* return the distance between two points */
  1203. Xdouble V2DistanceBetween2Points(a, b)
  1204. XPoint2 *a, *b;
  1205. X{
  1206. Xdouble dx = a->x - b->x;
  1207. Xdouble dy = a->y - b->y;
  1208. X    return(sqrt((dx*dx)+(dy*dy)));
  1209. X    };
  1210. X
  1211. X/* return the vector perpendicular to the input vector a */
  1212. XVector2 *V2MakePerpendicular(a, ap)
  1213. XVector2 *a, *ap;
  1214. X{
  1215. X    ap->x = -a->y;
  1216. X    ap->y = a->x;
  1217. X    return(ap);
  1218. X    };
  1219. X
  1220. X/* create, initialize, and return a new vector */
  1221. XVector2 *V2New(x, y)
  1222. Xdouble x, y;
  1223. X{
  1224. XVector2 *v = NEWTYPE(Vector2);
  1225. X    v->x = x;  v->y = y; 
  1226. X    return(v);
  1227. X    };
  1228. X    
  1229. X
  1230. X/* create, initialize, and return a duplicate vector */
  1231. XVector2 *V2Duplicate(a)
  1232. XVector2 *a;
  1233. X{
  1234. XVector2 *v = NEWTYPE(Vector2);
  1235. X    v->x = a->x;  v->y = a->y; 
  1236. X    return(v);
  1237. X    };
  1238. X    
  1239. X/* multiply a point by a matrix and return the transformed point */
  1240. XPoint2 *V2MulPointByMatrix(p, m)
  1241. XPoint2 *p;
  1242. XMatrix3 *m;
  1243. X{
  1244. Xdouble w;
  1245. X    p->x = (p->x * m->element[0][0]) + 
  1246. X             (p->y * m->element[1][0]) + m->element[2][0];
  1247. X    p->y = (p->x * m->element[0][1]) + 
  1248. X             (p->y * m->element[1][1]) + m->element[2][1];
  1249. X    w    = (p->x * m->element[0][2]) + 
  1250. X             (p->y * m->element[1][2]) + m->element[2][2];
  1251. X    if (w != 0.0) { p->x /= w;  p->y /= w; }
  1252. X    return(p);
  1253. X    };
  1254. X
  1255. X/* multiply together matrices c = ab */
  1256. X/* note that c must not point to either of the input matrices */
  1257. XMatrix3 *V2MatMul(a, b, c)
  1258. XMatrix3 *a, *b, *c;
  1259. X{
  1260. Xint i, j, k;
  1261. X    for (i=0; i<3; i++) {
  1262. X        for (j=0; j<3; j++) {
  1263. X            c->element[i][j] = 0;
  1264. X        for (k=0; k<3; k++) c->element[i][j] += 
  1265. X                a->element[i][k] * b->element[k][j];
  1266. X            };
  1267. X        };
  1268. X    return(c);
  1269. X    };
  1270. X
  1271. X
  1272. X
  1273. X
  1274. X/******************/
  1275. X/*   3d Library   */
  1276. X/******************/
  1277. X    
  1278. X/* returns squared length of input vector */    
  1279. Xdouble V3SquaredLength(a) 
  1280. XVector3 *a;
  1281. X{
  1282. X    return((a->x * a->x)+(a->y * a->y)+(a->z * a->z));
  1283. X    };
  1284. X
  1285. X/* returns length of input vector */
  1286. Xdouble V3Length(a) 
  1287. XVector3 *a;
  1288. X{
  1289. X    return(sqrt(V3SquaredLength(a)));
  1290. X    };
  1291. X
  1292. X/* negates the input vector and returns it */
  1293. XVector3 *V3Negate(v) 
  1294. XVector3 *v;
  1295. X{
  1296. X    v->x = -v->x;  v->y = -v->y;  v->z = -v->z;
  1297. X    return(v);
  1298. X    };
  1299. X
  1300. X/* normalizes the input vector and returns it */
  1301. XVector3 *V3Normalize(v) 
  1302. XVector3 *v;
  1303. X{
  1304. Xdouble len = V3Length(v);
  1305. X    if (len != 0.0) { v->x /= len;  v->y /= len; v->z /= len; };
  1306. X    return(v);
  1307. X    };
  1308. X
  1309. X/* scales the input vector to the new length and returns it */
  1310. XVector3 *V3Scale(v, newlen) 
  1311. XVector3 *v;
  1312. Xdouble newlen;
  1313. X{
  1314. Xdouble len = V3Length(v);
  1315. X    if (len != 0.0) {
  1316. X    v->x *= newlen/len;   v->y *= newlen/len;  v->z *= newlen/len;
  1317. X    };
  1318. X    return(v);
  1319. X    };
  1320. X
  1321. X
  1322. X/* return vector sum c = a+b */
  1323. XVector3 *V3Add(a, b, c)
  1324. XVector3 *a, *b, *c;
  1325. X{
  1326. X    c->x = a->x+b->x;  c->y = a->y+b->y;  c->z = a->z+b->z;
  1327. X    return(c);
  1328. X    };
  1329. X    
  1330. X/* return vector difference c = a-b */
  1331. XVector3 *V3Sub(a, b, c)
  1332. XVector3 *a, *b, *c;
  1333. X{
  1334. X    c->x = a->x-b->x;  c->y = a->y-b->y;  c->z = a->z-b->z;
  1335. X    return(c);
  1336. X    };
  1337. X
  1338. X/* return the dot product of vectors a and b */
  1339. Xdouble V3Dot(a, b) 
  1340. XVector3 *a, *b; 
  1341. X{
  1342. X    return((a->x*b->x)+(a->y*b->y)+(a->z*b->z));
  1343. X    };
  1344. X
  1345. X/* linearly interpolate between vectors by an amount alpha */
  1346. X/* and return the resulting vector. */
  1347. X/* When alpha=0, result=lo.  When alpha=1, result=hi. */
  1348. XVector3 *V3Lerp(lo, hi, alpha, result) 
  1349. XVector3 *lo, *hi, *result; 
  1350. Xdouble alpha;
  1351. X{
  1352. X    result->x = LERP(alpha, lo->x, hi->x);
  1353. X    result->y = LERP(alpha, lo->y, hi->y);
  1354. X    result->z = LERP(alpha, lo->z, hi->z);
  1355. X    return(result);
  1356. X    };
  1357. X
  1358. X/* make a linear combination of two vectors and return the result. */
  1359. X/* result = (a * ascl) + (b * bscl) */
  1360. XVector3 *V3Combine (a, b, result, ascl, bscl) 
  1361. XVector3 *a, *b, *result;
  1362. Xdouble ascl, bscl;
  1363. X{
  1364. X    result->x = (ascl * a->x) + (bscl * b->x);
  1365. X    result->y = (ascl * a->y) + (bscl * b->y);
  1366. X    result->y = (ascl * a->z) + (bscl * b->z);
  1367. X    return(result);
  1368. X    };
  1369. X
  1370. X
  1371. X/* multiply two vectors together component-wise and return the result */
  1372. XVector3 *V3Mul (a, b, result) 
  1373. XVector3 *a, *b, *result;
  1374. X{
  1375. X    result->x = a->x * b->x;
  1376. X    result->y = a->y * b->y;
  1377. X    result->z = a->z * b->z;
  1378. X    return(result);
  1379. X    };
  1380. X
  1381. X/* return the distance between two points */
  1382. Xdouble V3DistanceBetween2Points(a, b)
  1383. XPoint3 *a, *b;
  1384. X{
  1385. Xdouble dx = a->x - b->x;
  1386. Xdouble dy = a->y - b->y;
  1387. Xdouble dz = a->z - b->z;
  1388. X    return(sqrt((dx*dx)+(dy*dy)+(dz*dz)));
  1389. X    };
  1390. X
  1391. X/* return the cross product c = a cross b */
  1392. XVector3 *V3Cross(a, b, c)
  1393. XVector3 *a, *b, *c;
  1394. X{
  1395. X    c->x = (a->y*b->z) - (a->z*b->y);
  1396. X    c->y = (a->z*b->x) - (a->x*b->z);
  1397. X    c->z = (a->x*b->y) - (a->y*b->x);
  1398. X    return(c);
  1399. X    };
  1400. X
  1401. X/* create, initialize, and return a new vector */
  1402. XVector3 *V3New(x, y, z)
  1403. Xdouble x, y, z;
  1404. X{
  1405. XVector3 *v = NEWTYPE(Vector3);
  1406. X    v->x = x;  v->y = y;  v->z = z;
  1407. X    return(v);
  1408. X    };
  1409. X
  1410. X/* create, initialize, and return a duplicate vector */
  1411. XVector3 *V3Duplicate(a)
  1412. XVector3 *a;
  1413. X{
  1414. XVector3 *v = NEWTYPE(Vector3);
  1415. X    v->x = a->x;  v->y = a->y;  v->z = a->z;
  1416. X    return(v);
  1417. X    };
  1418. X
  1419. X    
  1420. X/* multiply a point by a matrix and return the transformed point */
  1421. XPoint3 *V3MulPointByMatrix(p, m)
  1422. XPoint3 *p;
  1423. XMatrix4 *m;
  1424. X{
  1425. Xdouble w;
  1426. X    p->x = (p->x * m->element[0][0]) + (p->y * m->element[1][0]) + 
  1427. X         (p->z * m->element[2][0]) + m->element[3][0];
  1428. X    p->y = (p->x * m->element[0][1]) + (p->y * m->element[1][1]) + 
  1429. X         (p->z * m->element[2][1]) + m->element[3][1];
  1430. X    p->z = (p->x * m->element[0][2]) + (p->y * m->element[1][2]) + 
  1431. X         (p->z * m->element[2][2]) + m->element[3][2];
  1432. X    w =    (p->x * m->element[0][3]) + (p->y * m->element[1][3]) + 
  1433. X         (p->z * m->element[2][3]) + m->element[3][3];
  1434. X    if (w != 0.0) { p->x /= w;  p->y /= w;  p->z /= w; }
  1435. X    return(p);
  1436. X    };
  1437. X
  1438. X/* multiply together matrices c = ab */
  1439. X/* note that c must not point to either of the input matrices */
  1440. XMatrix4 *V3MatMul(a, b, c)
  1441. XMatrix4 *a, *b, *c;
  1442. X{
  1443. Xint i, j, k;
  1444. X    for (i=0; i<4; i++) {
  1445. X        for (j=0; j<4; j++) {
  1446. X            c->element[i][j] = 0;
  1447. X            for (k=0; k<4; k++) c->element[i][j] += 
  1448. X                a->element[i][k] * b->element[k][j];
  1449. X            };
  1450. X        };
  1451. X    return(c);
  1452. X    };
  1453. X
  1454. X/* binary greatest common divisor by Silver and Terzian.  See Knuth */
  1455. X/* both inputs must be >= 0 */
  1456. Xgcd(u, v)
  1457. Xint u, v;
  1458. X{
  1459. Xint k, t, f;
  1460. X    if ((u<0) || (v<0)) return(1); /* error if u<0 or v<0 */
  1461. X    k = 0;  f = 1;
  1462. X    while ((0 == (u%2)) && (0 == (v%2))) {
  1463. X        k++;  u>>=1;  v>>=1,  f*=2;
  1464. X        };
  1465. X    if (u&01) { t = -v;  goto B4; } else { t = u; }
  1466. X    B3: if (t > 0) { t >>= 1; } else { t = -((-t) >> 1); };
  1467. X    B4: if (0 == (t%2)) goto B3;
  1468. X
  1469. X    if (t > 0) u = t; else v = -t;
  1470. X    if (0 != (t = u - v)) goto B3;
  1471. X    return(u*f);
  1472. X    };    
  1473. X
  1474. X/***********************/
  1475. X/*   Useful Routines   */
  1476. X/***********************/
  1477. X
  1478. X/* return roots of ax^2+bx+c */
  1479. X/* stable algebra derived from Numerical Recipes by Press et al.*/
  1480. Xint quadraticRoots(a, b, c, roots)
  1481. Xdouble a, b, c, *roots;
  1482. X{
  1483. Xdouble d, q;
  1484. Xint count = 0;
  1485. X    d = (b*b)-(4*a*c);
  1486. X    if (d < 0.0) { *roots = *(roots+1) = 0.0;  return(0); };
  1487. X    q =  -0.5 * (b + (SGN(b)*sqrt(d)));
  1488. X    if (a != 0.0)  { *roots++ = q/a; count++; }
  1489. X    if (q != 0.0) { *roots++ = c/q; count++; }
  1490. X    return(count);
  1491. X    };
  1492. X
  1493. X
  1494. X/* generic 1d regula-falsi step.  f is function to evaluate */
  1495. X/* interval known to contain root is given in left, right */
  1496. X/* returns new estimate */
  1497. Xdouble RegulaFalsi(f, left, right)
  1498. Xdouble (*f)(), left, right;
  1499. X{
  1500. Xdouble d = (*f)(right) - (*f)(left);
  1501. X    if (d != 0.0) return (right - (*f)(right)*(right-left)/d);
  1502. X    return((left+right)/2.0);
  1503. X    };
  1504. X
  1505. X/* generic 1d Newton-Raphson step. f is function, df is derivative */
  1506. X/* x is current best guess for root location. Returns new estimate */
  1507. Xdouble NewtonRaphson(f, df, x)
  1508. Xdouble (*f)(), (*df)(), x;
  1509. X{
  1510. Xdouble d = (*df)(x);
  1511. X    if (d != 0.0) return (x-((*f)(x)/d));
  1512. X    return(x-1.0);
  1513. X    };
  1514. X
  1515. X
  1516. X/* hybrid 1d Newton-Raphson/Regula Falsi root finder. */
  1517. X/* input function f and its derivative df, an interval */
  1518. X/* left, right known to contain the root, and an error tolerance */
  1519. X/* Based on Blinn */
  1520. Xdouble findroot(left, right, tolerance, f, df)
  1521. Xdouble left, right, tolerance;
  1522. Xdouble (*f)(), (*df)();
  1523. X{
  1524. Xdouble newx = left;
  1525. X    while (ABS((*f)(newx)) > tolerance) {
  1526. X        newx = NewtonRaphson(f, df, newx);
  1527. X        if (newx < left || newx > right) 
  1528. X            newx = RegulaFalsi(f, left, right);
  1529. X        if ((*f)(newx) * (*f)(left) <= 0.0) right = newx;  
  1530. X            else left = newx;
  1531. X        };
  1532. X    return(newx);
  1533. X    }; 
  1534. END_OF_FILE
  1535. if test 10092 -ne `wc -c <'GGVecLib.c'`; then
  1536.     echo shar: \"'GGVecLib.c'\" unpacked with wrong size!
  1537. fi
  1538. # end of 'GGVecLib.c'
  1539. fi
  1540. if test -f 'NearestPoint.c' -a "${1}" != "-c" ; then 
  1541.   echo shar: Will not clobber existing file \"'NearestPoint.c'\"
  1542. else
  1543. echo shar: Extracting \"'NearestPoint.c'\" \(12269 characters\)
  1544. sed "s/^X//" >'NearestPoint.c' <<'END_OF_FILE'
  1545. X/*
  1546. XSolving the Nearest Point-on-Curve Problem 
  1547. Xand
  1548. XA Bezier Curve-Based Root-Finder
  1549. Xby Philip J. Schneider
  1550. Xfrom "Graphics Gems", Academic Press, 1990
  1551. X*/
  1552. X
  1553. X /*    point_on_curve.c    */        
  1554. X                                    
  1555. X#include <stdio.h>
  1556. X#include <malloc.h>
  1557. X#include <math.h>
  1558. X#include "GraphicsGems.h"
  1559. X
  1560. X#define TESTMODE
  1561. X
  1562. X/*
  1563. X *  Forward declarations
  1564. X */
  1565. XPoint2  NearestPointOnCurve();
  1566. Xstatic    int    FindRoots();
  1567. Xstatic    Point2    *ConvertToBezierForm();
  1568. Xstatic    double    ComputeXIntercept();
  1569. Xstatic    int    ControlPolygonFlatEnough();
  1570. Xstatic    int    CrossingCount();
  1571. Xstatic    Point2    Bezier();
  1572. Xstatic    Vector2    V2ScaleII();
  1573. X
  1574. Xint        MAXDEPTH = 64;    /*  Maximum depth for recursion */
  1575. X
  1576. X#define    EPSILON    (ldexp(1.0,-MAXDEPTH-1)) /*Flatness control value */
  1577. X#define    DEGREE    3            /*  Cubic Bezier curve        */
  1578. X#define    W_DEGREE 5            /*  Degree of eqn to find roots of */
  1579. X
  1580. X#ifdef TESTMODE
  1581. X/*
  1582. X *  main :
  1583. X *    Given a cubic Bezier curve (i.e., its control points), and some
  1584. X *    arbitrary point in the plane, find the point on the curve
  1585. X *    closest to that arbitrary point.
  1586. X */
  1587. Xmain()
  1588. X{
  1589. X   
  1590. X static Point2 bezCurve[4] = {    /*  A cubic Bezier curve    */
  1591. X    { 0.0, 0.0 },
  1592. X    { 1.0, 2.0 },
  1593. X    { 3.0, 3.0 },
  1594. X    { 4.0, 2.0 },
  1595. X    };
  1596. X    static Point2 arbPoint = { 3.5, 2.0 }; /*Some arbitrary point*/
  1597. X    Point2    pointOnCurve;         /*  Nearest point on the curve */
  1598. X
  1599. X    /*  Find the closest point */
  1600. X    pointOnCurve = NearestPointOnCurve(arbPoint, bezCurve);
  1601. X    printf("pointOnCurve : (%4.4f, %4.4f)\n", pointOnCurve.x,
  1602. X        pointOnCurve.y);
  1603. X}
  1604. X#endif /* TESTMODE */
  1605. X
  1606. X
  1607. X/*
  1608. X *  NearestPointOnCurve :
  1609. X *      Compute the parameter value of the point on a Bezier
  1610. X *        curve segment closest to some arbtitrary, user-input point.
  1611. X *        Return the point on the curve at that parameter value.
  1612. X *
  1613. X */
  1614. XPoint2 NearestPointOnCurve(P, V)
  1615. X    Point2     P;            /* The user-supplied point      */
  1616. X    Point2     *V;            /* Control points of cubic Bezier */
  1617. X{
  1618. X    Point2    *w;            /* Ctl pts for 5th-degree eqn    */
  1619. X    double     t_candidate[W_DEGREE];    /* Possible roots        */     
  1620. X    int     n_solutions;        /* Number of roots found    */
  1621. X    double    t;            /* Parameter value of closest pt*/
  1622. X
  1623. X    /*  Convert problem to 5th-degree Bezier form    */
  1624. X    w = ConvertToBezierForm(P, V);
  1625. X
  1626. X    /* Find all possible roots of 5th-degree equation */
  1627. X    n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0);
  1628. X    free((char *)w);
  1629. X
  1630. X    /* Compare distances of P to all candidates, and to t=0, and t=1 */
  1631. X    {
  1632. X        double     dist, new_dist;
  1633. X        Point2     p;
  1634. X        Vector2  v;
  1635. X        int        i;
  1636. X
  1637. X    
  1638. X    /* Check distance to beginning of curve, where t = 0    */
  1639. X        dist = V2SquaredLength(V2Sub(&P, &V[0], &v));
  1640. X            t = 0.0;
  1641. X
  1642. X    /* Find distances for candidate points    */
  1643. X        for (i = 0; i < n_solutions; i++) {
  1644. X            p = Bezier(V, DEGREE, t_candidate[i], NULL, NULL);
  1645. X            new_dist = V2SquaredLength(V2Sub(&P, &p, &v));
  1646. X            if (new_dist < dist) {
  1647. X                    dist = new_dist;
  1648. X                    t = t_candidate[i];
  1649. X            }
  1650. X        }
  1651. X
  1652. X    /* Finally, look at distance to end point, where t = 1.0 */
  1653. X        new_dist = V2SquaredLength(V2Sub(&P, &V[DEGREE], &v));
  1654. X            if (new_dist < dist) {
  1655. X                dist = new_dist;
  1656. X            t = 1.0;
  1657. X        }
  1658. X    }
  1659. X
  1660. X    /*  Return the point on the curve at parameter value t */
  1661. X    printf("t : %4.12f\n", t);
  1662. X    return (Bezier(V, DEGREE, t, NULL, NULL));
  1663. X}
  1664. X
  1665. X
  1666. X/*
  1667. X *  ConvertToBezierForm :
  1668. X *        Given a point and a Bezier curve, generate a 5th-degree
  1669. X *        Bezier-format equation whose solution finds the point on the
  1670. X *      curve nearest the user-defined point.
  1671. X */
  1672. Xstatic Point2 *ConvertToBezierForm(P, V)
  1673. X    Point2     P;            /* The point to find t for    */
  1674. X    Point2     *V;            /* The control points        */
  1675. X{
  1676. X    int     i, j, k, m, n, ub, lb;    
  1677. X    double     t;            /* Value of t for point P    */
  1678. X    int     row, column;        /* Table indices        */
  1679. X    Vector2     c[DEGREE+1];        /* V(i)'s - P            */
  1680. X    Vector2     d[DEGREE];        /* V(i+1) - V(i)        */
  1681. X    Point2     *w;            /* Ctl pts of 5th-degree curve  */
  1682. X    double     cdTable[3][4];        /* Dot product of c, d        */
  1683. X    static double z[3][4] = {    /* Precomputed "z" for cubics    */
  1684. X    {1.0, 0.6, 0.3, 0.1},
  1685. X    {0.4, 0.6, 0.6, 0.4},
  1686. X    {0.1, 0.3, 0.6, 1.0},
  1687. X    };
  1688. X
  1689. X
  1690. X    /*Determine the c's -- these are vectors created by subtracting*/
  1691. X    /* point P from each of the control points                */
  1692. X    for (i = 0; i <= DEGREE; i++) {
  1693. X        V2Sub(&V[i], &P, &c[i]);
  1694. X    }
  1695. X    /* Determine the d's -- these are vectors created by subtracting*/
  1696. X    /* each control point from the next                    */
  1697. X    for (i = 0; i <= DEGREE - 1; i++) { 
  1698. X        d[i] = V2ScaleII(V2Sub(&V[i+1], &V[i], &d[i]), 3.0);
  1699. X    }
  1700. X
  1701. X    /* Create the c,d table -- this is a table of dot products of the */
  1702. X    /* c's and d's                            */
  1703. X    for (row = 0; row <= DEGREE - 1; row++) {
  1704. X        for (column = 0; column <= DEGREE; column++) {
  1705. X            cdTable[row][column] = V2Dot(&d[row], &c[column]);
  1706. X        }
  1707. X    }
  1708. X
  1709. X    /* Now, apply the z's to the dot products, on the skew diagonal*/
  1710. X    /* Also, set up the x-values, making these "points"        */
  1711. X    w = (Point2 *)malloc((unsigned)(W_DEGREE+1) * sizeof(Point2));
  1712. X    for (i = 0; i <= W_DEGREE; i++) {
  1713. X        w[i].y = 0.0;
  1714. X        w[i].x = (double)(i) / W_DEGREE;
  1715. X    }
  1716. X
  1717. X    n = DEGREE;
  1718. X    m = DEGREE-1;
  1719. X    for (k = 0; k <= n + m; k++) {
  1720. X        lb = MAX(0, k - m);
  1721. X        ub = MIN(k, n);
  1722. X        for (i = lb; i <= ub; i++) {
  1723. X            j = k - i;
  1724. X            w[i+j].y += cdTable[j][i] * z[j][i];
  1725. X        }
  1726. X    }
  1727. X
  1728. X    return (w);
  1729. X}
  1730. X
  1731. X
  1732. X/*
  1733. X *  FindRoots :
  1734. X *    Given a 5th-degree equation in Bernstein-Bezier form, find
  1735. X *    all of the roots in the interval [0, 1].  Return the number
  1736. X *    of roots found.
  1737. X */
  1738. Xstatic int FindRoots(w, degree, t, depth)
  1739. X    Point2     *w;            /* The control points        */
  1740. X    int     degree;        /* The degree of the polynomial    */
  1741. X    double     *t;            /* RETURN candidate t-values    */
  1742. X    int     depth;        /* The depth of the recursion    */
  1743. X{  
  1744. X    int     i;
  1745. X    Point2     Left[W_DEGREE+1],    /* New left and right         */
  1746. X              Right[W_DEGREE+1];    /* control polygons        */
  1747. X    int     left_count,        /* Solution count from        */
  1748. X        right_count;        /* children            */
  1749. X    double     left_t[W_DEGREE+1],    /* Solutions from kids        */
  1750. X               right_t[W_DEGREE+1];
  1751. X
  1752. X    switch (CrossingCount(w, degree)) {
  1753. X           case 0 : {    /* No solutions here    */
  1754. X         return 0;    
  1755. X         break;
  1756. X    }
  1757. X    case 1 : {    /* Unique solution    */
  1758. X        /* Stop recursion when the tree is deep enough    */
  1759. X        /* if deep enough, return 1 solution at midpoint     */
  1760. X        if (depth >= MAXDEPTH) {
  1761. X            t[0] = (w[0].x + w[W_DEGREE].x) / 2.0;
  1762. X            return 1;
  1763. X        }
  1764. X        if (ControlPolygonFlatEnough(w, degree)) {
  1765. X            t[0] = ComputeXIntercept(w, degree);
  1766. X            return 1;
  1767. X        }
  1768. X        break;
  1769. X    }
  1770. X}
  1771. X
  1772. X    /* Otherwise, solve recursively after    */
  1773. X    /* subdividing control polygon        */
  1774. X    Bezier(w, degree, 0.5, Left, Right);
  1775. X    left_count  = FindRoots(Left,  degree, left_t, depth+1);
  1776. X    right_count = FindRoots(Right, degree, right_t, depth+1);
  1777. X
  1778. X
  1779. X    /* Gather solutions together    */
  1780. X    for (i = 0; i < left_count; i++) {
  1781. X        t[i] = left_t[i];
  1782. X    }
  1783. X    for (i = 0; i < right_count; i++) {
  1784. X         t[i+left_count] = right_t[i];
  1785. X    }
  1786. X
  1787. X    /* Send back total number of solutions    */
  1788. X    return (left_count+right_count);
  1789. X}
  1790. X
  1791. X
  1792. X/*
  1793. X * CrossingCount :
  1794. X *    Count the number of times a Bezier control polygon 
  1795. X *    crosses the 0-axis. This number is >= the number of roots.
  1796. X *
  1797. X */
  1798. Xstatic int CrossingCount(V, degree)
  1799. X    Point2    *V;            /*  Control pts of Bezier curve    */
  1800. X    int        degree;            /*  Degreee of Bezier curve     */
  1801. X{
  1802. X    int     i;    
  1803. X    int     n_crossings = 0;    /*  Number of zero-crossings    */
  1804. X    int        sign, old_sign;        /*  Sign of coefficients    */
  1805. X
  1806. X    sign = old_sign = SGN(V[0].y);
  1807. X    for (i = 1; i <= degree; i++) {
  1808. X        sign = SGN(V[i].y);
  1809. X        if (sign != old_sign) n_crossings++;
  1810. X        old_sign = sign;
  1811. X    }
  1812. X    return n_crossings;
  1813. X}
  1814. X
  1815. X
  1816. X
  1817. X/*
  1818. X *  ControlPolygonFlatEnough :
  1819. X *    Check if the control polygon of a Bezier curve is flat enough
  1820. X *    for recursive subdivision to bottom out.
  1821. X *
  1822. X */
  1823. Xstatic int ControlPolygonFlatEnough(V, degree)
  1824. X    Point2    *V;        /* Control points    */
  1825. X    int     degree;        /* Degree of polynomial    */
  1826. X{
  1827. X    int     i;            /* Index variable        */
  1828. X    double     *distance;        /* Distances from pts to line    */
  1829. X    double     max_distance_above;    /* maximum of these        */
  1830. X    double     max_distance_below;
  1831. X    double     error;            /* Precision of root        */
  1832. X    Vector2     t;            /* Vector from V[0] to V[degree]*/
  1833. X    double     intercept_1,
  1834. X               intercept_2,
  1835. X               left_intercept,
  1836. X               right_intercept;
  1837. X    double     a, b, c;        /* Coefficients of implicit    */
  1838. X                        /* eqn for line from V[0]-V[deg]*/
  1839. X
  1840. X    /* Find the  perpendicular distance        */
  1841. X    /* from each interior control point to     */
  1842. X    /* line connecting V[0] and V[degree]    */
  1843. X    distance = (double *)malloc((unsigned)(degree + 1) *                     sizeof(double));
  1844. X    {
  1845. X    double    abSquared;
  1846. X
  1847. X    /* Derive the implicit equation for line connecting first *'
  1848. X    /*  and last control points */
  1849. X    a = V[0].y - V[degree].y;
  1850. X    b = V[degree].x - V[0].x;
  1851. X    c = V[0].x * V[degree].y - V[degree].x * V[0].y;
  1852. X
  1853. X    abSquared = (a * a) + (b * b);
  1854. X
  1855. X        for (i = 1; i < degree; i++) {
  1856. X        /* Compute distance from each of the points to that line    */
  1857. X            distance[i] = a * V[i].x + b * V[i].y + c;
  1858. X            if (distance[i] > 0.0) {
  1859. X                distance[i] = (distance[i] * distance[i]) / abSquared;
  1860. X            }
  1861. X            if (distance[i] < 0.0) {
  1862. X                distance[i] = -((distance[i] * distance[i]) /                         abSquared);
  1863. X            }
  1864. X        }
  1865. X    }
  1866. X
  1867. X
  1868. X    /* Find the largest distance    */
  1869. X    max_distance_above = 0.0;
  1870. X    max_distance_below = 0.0;
  1871. X    for (i = 1; i < degree; i++) {
  1872. X        if (distance[i] < 0.0) {
  1873. X            max_distance_below = MIN(max_distance_below, distance[i]);
  1874. X        };
  1875. X        if (distance[i] > 0.0) {
  1876. X            max_distance_above = MAX(max_distance_above, distance[i]);
  1877. X        }
  1878. X    }
  1879. X    free((char *)distance);
  1880. X
  1881. X    {
  1882. X    double    det, dInv;
  1883. X    double    a1, b1, c1, a2, b2, c2;
  1884. X
  1885. X    /*  Implicit equation for zero line */
  1886. X    a1 = 0.0;
  1887. X    b1 = 1.0;
  1888. X    c1 = 0.0;
  1889. X
  1890. X    /*  Implicit equation for "above" line */
  1891. X    a2 = a;
  1892. X    b2 = b;
  1893. X    c2 = c + max_distance_above;
  1894. X
  1895. X    det = a1 * b2 - a2 * b1;
  1896. X    dInv = 1.0/det;
  1897. X    
  1898. X    intercept_1 = (b1 * c2 - b2 * c1) * dInv;
  1899. X
  1900. X    /*  Implicit equation for "below" line */
  1901. X    a2 = a;
  1902. X    b2 = b;
  1903. X    c2 = c + max_distance_below;
  1904. X    
  1905. X    det = a1 * b2 - a2 * b1;
  1906. X    dInv = 1.0/det;
  1907. X    
  1908. X    intercept_2 = (b1 * c2 - b2 * c1) * dInv;
  1909. X    }
  1910. X
  1911. X    /* Compute intercepts of bounding box    */
  1912. X    left_intercept = MIN(intercept_1, intercept_2);
  1913. X    right_intercept = MAX(intercept_1, intercept_2);
  1914. X
  1915. X    error = 0.5 * (right_intercept-left_intercept);    
  1916. X    if (error < EPSILON) {
  1917. X        return 1;
  1918. X    }
  1919. X    else {
  1920. X        return 0;
  1921. X    }
  1922. X}
  1923. X
  1924. X
  1925. X
  1926. X/*
  1927. X *  ComputeXIntercept :
  1928. X *    Compute intersection of chord from first control point to last
  1929. X *      with 0-axis.
  1930. X * 
  1931. X */
  1932. Xstatic double ComputeXIntercept(V, degree)
  1933. X    Point2     *V;            /*  Control points    */
  1934. X    int        degree;         /*  Degree of curve    */
  1935. X{
  1936. X    double    XLK, YLK, XNM, YNM, XMK, YMK;
  1937. X    double    det, detInv;
  1938. X    double    S, T;
  1939. X    double    X, Y;
  1940. X
  1941. X    XLK = 1.0 - 0.0;
  1942. X    YLK = 0.0 - 0.0;
  1943. X    XNM = V[degree].x - V[0].x;
  1944. X    YNM = V[degree].y - V[0].y;
  1945. X    XMK = V[0].x - 0.0;
  1946. X    YMK = V[0].y - 0.0;
  1947. X
  1948. X    det = XNM*YLK - YNM*XLK;
  1949. X    detInv = 1.0/det;
  1950. X
  1951. X    S = (XNM*YMK - YNM*XMK) * detInv;
  1952. X    T = (XLK*YMK - YLK*XMK) * detInv;
  1953. X    
  1954. X    X = 0.0 + XLK * S;
  1955. X    Y = 0.0 + YLK * S;
  1956. X
  1957. X    return X;
  1958. X}
  1959. X
  1960. X
  1961. X/*
  1962. X *  Bezier : 
  1963. X *    Evaluate a Bezier curve at a particular parameter value
  1964. X *      Fill in control points for resulting sub-curves if "Left" and
  1965. X *    "Right" are non-null.
  1966. X * 
  1967. X */
  1968. Xstatic Point2 Bezier(V, degree, t, Left, Right)
  1969. X    int     degree;        /* Degree of bezier curve    */
  1970. X    Point2     *V;            /* Control pts            */
  1971. X    double     t;            /* Parameter value        */
  1972. X    Point2     *Left;        /* RETURN left half ctl pts    */
  1973. X    Point2     *Right;        /* RETURN right half ctl pts    */
  1974. X{
  1975. X    int     i, j;        /* Index variables    */
  1976. X    Point2     Vtemp[W_DEGREE+1][W_DEGREE+1];
  1977. X
  1978. X
  1979. X    /* Copy control points    */
  1980. X    for (j =0; j <= degree; j++) {
  1981. X        Vtemp[0][j] = V[j];
  1982. X    }
  1983. X
  1984. X    /* Triangle computation    */
  1985. X    for (i = 1; i <= degree; i++) {    
  1986. X        for (j =0 ; j <= degree - i; j++) {
  1987. X            Vtemp[i][j].x =
  1988. X                  (1.0 - t) * Vtemp[i-1][j].x + t * Vtemp[i-1][j+1].x;
  1989. X            Vtemp[i][j].y =
  1990. X                  (1.0 - t) * Vtemp[i-1][j].y + t * Vtemp[i-1][j+1].y;
  1991. X        }
  1992. X    }
  1993. X    
  1994. X    if (Left != NULL) {
  1995. X        for (j = 0; j <= degree; j++) {
  1996. X            Left[j]  = Vtemp[j][0];
  1997. X        }
  1998. X    }
  1999. X    if (Right != NULL) {
  2000. X        for (j = 0; j <= degree; j++) {
  2001. X            Right[j] = Vtemp[degree-j][j];
  2002. X        }
  2003. X    }
  2004. X
  2005. X    return (Vtemp[degree][0]);
  2006. X}
  2007. X
  2008. Xstatic Vector2 V2ScaleII(v, s)
  2009. X    Vector2    *v;
  2010. X    double    s;
  2011. X{
  2012. X    Vector2 result;
  2013. X
  2014. X    result.x = v->x * s; result.y = v->y * s;
  2015. X    return (result);
  2016. X}
  2017. END_OF_FILE
  2018. if test 12269 -ne `wc -c <'NearestPoint.c'`; then
  2019.     echo shar: \"'NearestPoint.c'\" unpacked with wrong size!
  2020. fi
  2021. # end of 'NearestPoint.c'
  2022. fi
  2023. echo shar: End of archive 5 \(of 5\).
  2024. cp /dev/null ark5isdone
  2025. MISSING=""
  2026. for I in 1 2 3 4 5 ; do
  2027.     if test ! -f ark${I}isdone ; then
  2028.     MISSING="${MISSING} ${I}"
  2029.     fi
  2030. done
  2031. if test "${MISSING}" = "" ; then
  2032.     echo You have unpacked all 5 archives.
  2033.     rm -f ark[1-9]isdone
  2034. else
  2035.     echo You still need to unpack the following archives:
  2036.     echo "        " ${MISSING}
  2037. fi
  2038. ##  End of shell archive.
  2039. exit 0
  2040.  
  2041.